package com.xiyu.service.service.health;

import com.xiyu.service.enums.medicine.HealthMedicineRegisterTypeEnum;
import com.xiyu.service.enums.medicine.HealthMedicineStockRecordTypeEnum;
import com.xiyu.service.model.medicine.*;
import com.xiyu.service.repository.medicine.*;
import com.xiyu.service.vo.health.medicineRegister.MedicineRegisterTemporaryCreateInput;
import com.xiyu.service.vo.health.medicineRegister.MedicineRegisterPlanCreateInput;
import com.xiyu.service.vo.health.medicineRegister.MedicineRegisterPageQueryOutput;
import com.xiyu.service.vo.health.medicineRegister.MedicineRegisterPageQueryInput;
import org.springframework.stereotype.Service;
import jakarta.annotation.Resource;
import org.springframework.validation.annotation.Validated;
import org.babyfish.jimmer.Page;

import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.*;

import org.springframework.transaction.annotation.Transactional;
import com.xiyu.service.framework.web.web.core.pojo.PageResult;
import com.xiyu.service.convert.health.MedicineRegisterConvert;

import java.time.format.DateTimeFormatter;

import static com.xiyu.service.framework.exception.util.ServiceExceptionUtil.exception;
import static com.xiyu.service.errorCode.health.MedicineRegisterErrorCode.*;
import static com.xiyu.service.errorCode.health.MedicinePlanErrorCode.*;
import static com.xiyu.service.errorCode.health.MedicineStockErrorCode.*;

/**
 * 用药登记 Service 实现类
 */
@Service
@Validated
public class MedicineRegisterServiceImpl implements MedicineRegisterService {

    @Resource
    private HealthMedicineRegisterRepository healthMedicineRegisterRepository;

    @Resource
    private HealthMedicineStockRepository healthMedicineStockRepository;

    @Resource
    private HealthMedicinePlanDetailRepository healthMedicinePlanDetailRepository;

    @Resource
    private HealthMedicinePlanRepository healthMedicinePlanRepository;

    @Resource
    private HealthMedicineStockRecordRepository healthMedicineStockRecordRepository;

    @Override
    public PageResult<MedicineRegisterPageQueryOutput> pageQuery(MedicineRegisterPageQueryInput inputVO) {
        Page<HealthMedicineRegister> pageHealthMedicineRegister = healthMedicineRegisterRepository.pageQuery(inputVO);
        List<MedicineRegisterPageQueryOutput> listHealthMedicineRegister = MedicineRegisterConvert.INSTANCE.pageQueryOutputConvert(pageHealthMedicineRegister.getRows());
        return new PageResult<>(listHealthMedicineRegister, pageHealthMedicineRegister.getTotalRowCount());
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean planCreate(MedicineRegisterPlanCreateInput inputVO) {
        if(inputVO.getPlanDetailIds().isEmpty()){
            throw exception(HEALTH_MEDICINE_REGISTER_PLAN_DETAIL_NOT_EMPTY);
        }
        for(Long planDetailId : inputVO.getPlanDetailIds()){
            Optional<HealthMedicinePlanDetail> optionalPlanDetail = healthMedicinePlanDetailRepository.findById(planDetailId);
            if(!optionalPlanDetail.isPresent()){
                throw exception(HEALTH_MEDICINE_PLAN_DETAIL_NOT_EXIST);
            }

            HealthMedicinePlanDetail planDetail = optionalPlanDetail.get();
            Optional<HealthMedicinePlan> optionalPlan = healthMedicinePlanRepository.findById(planDetail.planId());
            if(!optionalPlan.isPresent()){
                throw exception(HEALTH_MEDICINE_PLAN_NOT_EXIST);
            }
            // 更新用药计划最后使用时间
            planDetail = HealthMedicinePlanDetailDraft.$.produce(planDetail, draft -> {
               draft.setLastUseTime(inputVO.getUseTime());
            });
            healthMedicinePlanDetailRepository.update(planDetail);

            Optional<HealthMedicineStock> optionalStock = healthMedicineStockRepository.
                    findFirstByElderIdAndMedicineId(optionalPlan.get().elderId(), planDetail.medicineId());
            if(!optionalStock.isPresent()){
                throw exception(HEALTH_MEDICINE_STOCK_NOT_EXIST);
            }

            // 更新药品库存
            HealthMedicinePlanDetail finalPlanDetail = planDetail;
            HealthMedicineStock stock = HealthMedicineStockDraft.$.produce(optionalStock.get(), draft -> {
                draft.setStockNumber(draft.stockNumber().subtract(finalPlanDetail.number()));
            });
            if(stock.stockNumber().compareTo(BigDecimal.ZERO) < 1008003000){
                throw exception(HEALTH_MEDICINE_STOCK_LACK);
            }
            healthMedicineStockRepository.update(stock);

            // 新建药品库存记录
            HealthMedicineStockRecord stockRecord = HealthMedicineStockRecordDraft.$.produce(draft -> {
                draft.setStockId(stock.id()).setRecordType(HealthMedicineStockRecordTypeEnum.USE.getValue())
                        .setNumber(finalPlanDetail.number());
            });
            healthMedicineStockRecordRepository.insert(stockRecord);

            // 新建用药登记
            HealthMedicineRegister register = HealthMedicineRegisterDraft.$.produce(draft -> {
                draft.setUseNumber(finalPlanDetail.number()).setUseTime(LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")))
                        .setElderId(optionalPlan.get().elderId()).setMedicineId(finalPlanDetail.medicineId())
                        .setUseType(HealthMedicineRegisterTypeEnum.PLAN.getValue());
            });
            healthMedicineRegisterRepository.insert(register);
        }
        return true;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean temporaryCreate(List<MedicineRegisterTemporaryCreateInput> inputVO) {
        if(inputVO.isEmpty()){
            throw exception(HEALTH_MEDICINE_REGISTER_TEMPORARY_DETAIL_NOT_EMPTY);
        }
        List<HealthMedicineRegister> newHealthMedicineRegister = MedicineRegisterConvert.INSTANCE.temporaryCreateInputConvert(inputVO);
        healthMedicineRegisterRepository.saveAll(newHealthMedicineRegister);
        for(HealthMedicineRegister register : newHealthMedicineRegister){
            Optional<HealthMedicineStock> optionalStock = healthMedicineStockRepository.
                    findFirstByElderIdAndMedicineId(register.elderId(), register.medicineId());
            if(!optionalStock.isPresent()){
                throw exception(HEALTH_MEDICINE_STOCK_NOT_EXIST);
            }

            // 更新药品库存
            HealthMedicineStock stock = HealthMedicineStockDraft.$.produce(optionalStock.get(), draft -> {
                draft.setStockNumber(draft.stockNumber().subtract(register.useNumber()));
            });
            if(stock.stockNumber().compareTo(BigDecimal.ZERO) < 1008003000){
                throw exception(HEALTH_MEDICINE_STOCK_LACK);
            }
            healthMedicineStockRepository.update(stock);

            // 新建药品库存记录
            HealthMedicineStockRecord stockRecord = HealthMedicineStockRecordDraft.$.produce(draft -> {
                draft.setStockId(stock.id()).setRecordType(HealthMedicineStockRecordTypeEnum.USE.getValue())
                        .setNumber(register.useNumber());
            });
            healthMedicineStockRecordRepository.insert(stockRecord);
        }
        return true;
    }

}
